package org.ala.tiktools.rpc.kcp.client_server;

import java.util.concurrent.CompletableFuture;

import org.ala.tiktools.rpc.kcp.config.RpcKcpConfigInfo;
import org.ala.tiktools.rpc.kcp.netty.client.KcpClientChannel;
import org.ala.tiktools.rpc.kcp.netty.server.KcpServerChannel;

import io.netty.bootstrap.KcpClientBootstrap;
import io.netty.bootstrap.KcpServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;

/**
 *
 *	@author ala
 *	@date 2025年4月19日
 */
public class KcpNettyTools {

	
	/************************************************************************************************
	 * 服务端相关
	 ************************************************************************************************/
	/**
	 * 	服务端bootstrap
	 */
	static KcpServerBootstrap serverBootstrap;
	/**
	 * 	构建服务端bootstrap
	 */
	private static KcpServerBootstrap serverBootstrap(int bossCount, ChannelInitializer<Channel> initializer) {
		if (serverBootstrap == null) {
			synchronized (KcpNettyTools.class) {
				if (serverBootstrap == null) {
					serverBootstrap = new KcpServerBootstrap();
					serverBootstrap.group(new NioEventLoopGroup(bossCount));
					//	childOptions省略了，kcp直接从RpcKcpConfigInfo里拿配置
					serverBootstrap.channel(KcpServerChannel.class);
					serverBootstrap.childHandler(initializer);
				}
			}
		}
		return serverBootstrap;
	}
	/**
	 * 	构建kcp服务端
	 */
	public static KcpServerChannel[] bind(int[] ports, ChannelInitializer<Channel> initializer) {
		try {
			CompletableFuture<KcpServerChannel[]> cf = serverBootstrap(ports.length, initializer).binds(ports);
			return cf.get();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/************************************************************************************************
	 * 客户端相关
	 ************************************************************************************************/
	/**
	 * 	客户端bootstrap
	 */
	static KcpClientBootstrap clientBootstrap;
	private static KcpClientBootstrap clientBootstrap(int workerCount, ChannelInitializer<Channel> initializer) {
		if (clientBootstrap == null) {
			synchronized (KcpNettyTools.class) {
				if (clientBootstrap == null) {
					clientBootstrap = new KcpClientBootstrap();
					clientBootstrap.group(new NioEventLoopGroup(workerCount));
					clientBootstrap.channel(KcpClientChannel.class);
					clientBootstrap.handler(initializer);
				}
			}
		}
		return clientBootstrap;
	}
	/**
	 * 	连接服务端
	 * 	<p>	虚拟链接，只持有udp配置，并不真实持有网络套接字
	 */
	public static CompletableFuture<Channel> connect(String host, int port, ChannelInitializer<Channel> initializer) {
		CompletableFuture<Channel> cf = new CompletableFuture<>();
		ChannelFuture _cf = clientBootstrap(RpcKcpConfigInfo.INSTANCE.getWorkerCount(), initializer).connect(host, port);
		_cf.addListener(c -> {
			if (!c.isSuccess()) {
				cf.completeExceptionally(c.cause());
			} else {
				cf.complete((Channel)_cf.channel());
			}
		});
		return cf;
	}
}
